package com.huangsm.cloud.microservicerabbitmq.config;

import lombok.NoArgsConstructor;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置RabbitMq交换机消息配置
 * Exchange分发消息时根据类型的不同分发策略有区别，
 * 目前共四种类型：direct、fanout、topic、headers 。只说前三种模式。
 * @author huang
 * @PACKAGE_NAME com.huangsm.cloud.microservicerabbitmq.config
 * @PROJECT_NAME microservice-springcloud
 * @date 2019/1/17
 */
@Configuration
@NoArgsConstructor
public class RabbitExchangeConfig {
    @Autowired
    private RabbitAdmin rabbitAdmin;

    /**
     * Fanout模式
     * 每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。
     * fanout 交换器不处理路由键，只是简单的将队列绑定到交换器上，
     * 每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。
     * 很像子网广播，每台子网内的主机都获得了一份复制的消息。
     * fanout 类型转发消息是最快的。
     * @return
     */
    @Bean
    FanoutExchange contractFanoutExchange() {
        FanoutExchange fanoutExchange = new FanoutExchange("com.exchange.fanout");
        this.rabbitAdmin.declareExchange(fanoutExchange);
        return fanoutExchange;
    }

    /**
     * Topic模式
     * topic 交换器通过模式匹配分配消息的路由键属性，将路由键和某个模式进行匹配，
     * 此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词，
     * 这些单词之间用点隔开。它同样也会识别两个通配符：符号“#”和符号“*”。
     * #匹配0个或多个单词，*匹配一个单词。
     * @return
     */
    @Bean
    TopicExchange contractTopicExchangeDurable() {
        TopicExchange contractTopicExchange = new TopicExchange("com.exchange.topic");
        this.rabbitAdmin.declareExchange(contractTopicExchange);
        return contractTopicExchange;
    }

    /**
     * Direct模式
     * 消息中的路邮键(routing key)如果和 Binding 中的 binding key 一致，
     * 交换器就将消息发到对应的队列中。路由键与队列名完全匹配
     * @return
     */
    @Bean
    DirectExchange contractDirectExchange() {
        DirectExchange contractDirectExchange = new DirectExchange("com.exchange.direct");
        this.rabbitAdmin.declareExchange(contractDirectExchange);
        return contractDirectExchange;
    }

    /**
     * 配置消息队列
     * @return
     */
    @Bean
    Queue queueHello() {
        Queue queue = new Queue("com.queue.notify.hello", true);
        this.rabbitAdmin.declareQueue(queue);
        return queue;
    }
}
